﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using awsomeSyntezator.PipeLine.Envelopes;
using awsomeSyntezator.PipeLine.Filters;
using awsomeSyntezator.PipeLine.Oscilators;
using awsomeSyntezator.PipeLine.Oscilators.Effects;

namespace awsomeSyntezator.PipeLine
{
    public class Pipe : Block
    {
        public List<Block> Componenets;

        public Pipe ()
        {
            Componenets = new List<Block>();
            type = 5;
        }

        public void addComponent(Block component)
        {
            Componenets.Add(component);
        }
        public void addComponentAt(Block component, int i)
        {
            if(Componenets.Count == 0)
            {
                Componenets.Add(component);
            }
            else
            {
                if (Componenets[0].type == 1)
                {
                    Componenets[0] = new OscilatorPack((Oscilator) Componenets[0]);
                }
            }
            // do napisania
        }
        public override double getSample(int n, double sample)
        {
            for (int i = 0; i < Componenets.Count; i++ )
            {
                sample = Componenets[i].getSample(n, sample);
            }
            return sample;
        }
        public void addOscilator (float freq, int type, int strengh)
        {
            switch(type)
            {
				case 0: addComponentAt(new SINwawe(freq, Options.rate, strengh), 0); break;
				case 1: addComponentAt(new SQRwawe(freq, Options.rate, strengh), 0); break;
				case 2: addComponentAt(new SAWwawe(freq, Options.rate, strengh), 0); break;
				case 3: addComponentAt(new TRIwawe(freq, Options.rate, strengh), 0); break;
				case 4: addComponentAt(new WhiteNoise(freq, strengh), 0); break;
				case 5: addComponentAt(new RedNoise(Options.noiseDensity, strengh), 0); break;
				case 6: addComponentAt(new Pulse(freq, strengh), 0); break;
				case 7: addComponentAt(new Wind(Options.effectResonance, strengh), 0); break;
				case 8: addComponentAt(new RocketEngine(strengh), 0); break;
				case 9: addComponentAt(new Rain(strengh), 0); break;
				default: addComponentAt(new SINwawe(freq, Options.rate, strengh), 0); break;
            }
        }
        public void addEnvelope(float strenght, int type, int frequency)
        {
            switch (type)
            {
                case 0: addComponent(new FadeOut(strenght)); break;
                case 1: addComponent(new FadeIn(strenght)); break;
				case 2: addComponent(new Tremolo(strenght, frequency)); break;
                default: addComponent(new FadeOut(1)); break;

            }
        }
        public void addEffect(float freq, double resonance, int type)
        {
			switch (type)
			{
				case 0: addComponent(new HighCutOffFilter(freq, resonance)); break;
				case 1: addComponent(new LowCutOffFilter(freq, resonance)); break;
				case 2: addComponent(new MiddleCutOffFilter(freq, resonance)); break;
				default: addComponent(new LowCutOffFilter(freq, resonance)); break;

			}
        }

		public void generatePipe(float freq)
		{
            Componenets.Clear();
			if(Options.harmonics.Count > 0 )
			{
				OscilatorPack packet = new OscilatorPack();
				packet.generateHarmonics(Options.harmonics,freq, Options.defaultOscilator);
				Componenets.Add(packet);
			}
			else
			{
				addOscilator(freq, Options.defaultOscilator, 1);
			}

			if(Options.envelope)
			{
				if(Options.fadeInOut)
				{
					addEnvelope(Options.envelopeStrengh, 1, 1);
				}
				else
				{
					addEnvelope(Options.envelopeStrengh, 0, 1);
				}
			}
			if(Options.vibrato)
			{
				addEnvelope(Options.vibratoStrengh, 2, Options.vibratoFrequency);
			}
			if(Options.filter1)
			{
				addEffect(Options.filter1freq, Options.filter1resonance,0);
			}
			if (Options.filter2)
			{
				addEffect(Options.filter1freq, Options.filter1resonance, 1);
			}
			if (Options.filter3)
			{
				addEffect(Options.filter1freq, Options.filter1resonance, 2);
			}
		}
		public void generateExtraEffect(int type)
		{
			switch (type)
			{
				case 7 :	//wind effect
					Componenets.Add(new Wind(Options.effectResonance,1));
					break;
				case 8:		//rocket Engine
					Componenets.Add(new RocketEngine(1));
					break;
				case 9:		//rocket Engine
					Componenets.Add(new Rain(1));
					break;
				default:
					addOscilator(Options.freq,0,1);
					break;

			}
		}
    }
}
